package com.otherTest.java8;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.otherTest.pojo.User;
import org.junit.Test;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;


/**
 * 拉姆达表达式
 *
 * @author Conceit
 * @version 1.0, 2017/4/3
 */
public class TestLambda {

    //传统内部类 调用多线程
    @Test
    public void testrun() {

        for (int i = 0; i <= 20; i++) {
            final int finalI = i;
            new Thread(new Runnable() {

                public void run() {

                    System.out.println("传统方式调用多线程！" + finalI);

                }

            }).start();

        }
    }

    //用lambda表达式调用多线程
    @Test
    public void testLambda() {

        new Thread(() ->
                System.out.println("Lambd调用多线程！")
        ).start();

//        try {
//            TimeUnit.SECONDS.sleep((long) 1000f);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

    }

    //lambda 步步实践
    @Test
    public void testLambda2() {
        //////////////////////////////////////lambda 遍历list ///////////////////////////////////
        User user = new User();
        user.setId(1);
        user.setUsername("zhaohang");
        User user2 = new User();
        user2.setId(2);
        user2.setUsername("zhaodi");
        User user3 = new User();
        user3.setId(3);
        user3.setUsername("zhaojie");


        List<User> userList = new ArrayList<>();
        userList.add(user);
        userList.add(user2);
        userList.add(user3);


        //接受一个 User 对象 u,并在控制台打印
        //userList.forEach((User u)->System.out.println(u));
        //自动推导类型
        //userList.forEach(u->System.out.println(u));

        // 在 Java 8 中使用双冒号操作符
        //userList.forEach(System.out::println);
        /////////////////////////////////////////lambda 遍历list 完成///////////////////////////////////


    }

    //Stream API
    @Test
    public void testLambda3() {
        //////////////////////////////////Stream API////////////////////////////////////////
        List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
        //传统调用判断list中包含某个元素
//        for(Object o:languages){
//            if(o.toString().contains("a")){
//                System.out.println(o.toString());
//            }
//        }

        //Stream Api
        //将list中元素长度大于4的过滤，并放入新的List
        //Collectors.toList()是Collector的实现，用来把元素添加到ArrayList中
        //collect()方法接受一个Stream并将它们收集到一个结果容器中
        //也可以使用笨办法
        //如何创建结果容器（比如说，使用ArrayList::new方法）
        //如何把单个元素添加到容器中(比如使用ArrayList::add方法
        //如何把一个结果集合并到另一个中（比如使用ArrayList::addAll方法）

        List<String> result = (List<String>) languages.stream().filter(x -> (x.toString().length() == 4)).collect(toList());
        result.forEach(System.out::println);


    }

    /**
     * 高阶函数
     * 接收函数的函数
     * <p>
     * 函数接口类型一共有四种
     * Function<T,R> 接收一个T类型的参数，返回一个R类型的结果
     * Predicate<T> 接口 接收一个T类型的参数，返回一个boolean类型的结果
     * Consumer<T> 接收一个T类型的参数，不返回值
     * Supplier<T> 不接受参数，返回一个T类型的结果
     * filter 就是接受Predicate类型的函数方法
     */
    @Test
    public void testLambda4() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 8);
        //Predicate默认返回的结束boolean
        Predicate<Integer> selector = testLambda4Predicate();

        // System.out.println(this.testLambda4(numbers,selector));

        //或者
        //System.out.println(this.testLambda4(numbers,e -> e % 2 == 0));

        //或者直接调用外部方法
        //方法当做参数传到stream内部，使stream的每个元素都传入到该方法里面执行一下
        System.out.println(this.testLambda4(numbers, null));

    }

    public int testLambda4(List<Integer> values, Predicate<Integer> selector) {
        //return values.stream().filter(selector).reduce(0,(a, b) -> a+b);
        //return values.stream().filter(selector).reduce(0,Integer::sum);
        //return values.stream().filter(selector).mapToInt(x->x).sum();

        //用双冒号判断
        return values.stream().filter(Lambda4Predicate::testLambda4Predicate).reduce(0, Integer::sum);

    }


    public static Predicate<Integer> testLambda4Predicate() {
        return e -> e % 2 == 0;
    }


    /**
     * 高阶操作
     * 函数可以接收函数、lambda 表达式或方法引用作为参数
     * 同样地
     * 函数也可以返回 lambda 表达式或方法引用。
     * 在此情况下，返回类型将是函数接口
     */
    @Test
    public void testLambda5() {
        //Predicate<Integer> selector=testLambda4Predicate();
        Predicate<Integer> selector = Lambda4Predicate.testLambda4PredicateReturn();
        //Predicate<Integer> selector=e -> e % 2 == 0;
        System.out.println(selector.test(1));
    }


    /**
     * reusable
     * 可重用lambda表达式，创建接口
     * 使用自定义接口的默认apply方法
     */
    @Test
    public void testLambda6() {
        List<Integer> valuesOver25 = Arrays.asList(1, 2, 3, 4, 5, 80, 90, 100, 110, 120);

        valuesOver25 = valuesOver25.stream()
                .filter(LambdaFuncation.isGreaterThan.apply(50))
                .collect(toList());

        //提取成为函数接口
        System.out.println(valuesOver25);

    }


    @Test
    public void testLambda7() {
        Stream.of(1, 2, 3, 5, 99, 4, 88, 0).sorted().forEach(System.out::println);
    }

    @Test
    public void test() {
        String string = "10";

        //Stream.of(integers).forEach(System.out::println);
        System.out.println(new String[]{string});
    }

    @Test
    public void test2() {
        BigDecimal bigDecimal1 = new BigDecimal(100);
        BigDecimal bigDecimal2 = new BigDecimal(99);
        BigDecimal bigDecimal3 = new BigDecimal(100);
        BigDecimal bigDecimal4 = new BigDecimal(101);

        if (bigDecimal1.compareTo(bigDecimal4) != 1) {
            System.out.println("bigDecimal1.compareTo(bigDecimal1)==-1");
        }
    }

    @Test
    public void test3() {
        Set<Integer> set = new HashSet<>();
        set.add(1);
        set.add(2);
        System.out.println(JSONObject.toJSON(set));
    }

    @Test
    public void test4() {
        Integer[] integers = {99, 0, 45, 88, 77, 3, 50, 80};
        Stream.of(integers).sorted(Comparator.reverseOrder()).forEach(System.out::println);
        System.out.println("---------");
        Stream.of(integers).sorted().forEach(System.out::println);
    }

    /**
     * 排序
     */
    @Test
    public void test5() {
        List<Integer> integerList1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<Integer> integerList2 = Arrays.asList(2, 7, 9);
        List<Integer> integerList3 = null;

        //顺序
        Collections.sort(integerList1);
        integerList1.stream().forEach(System.out :: println);
        //倒序
        Collections.reverse(integerList1);
        integerList1.stream().forEach(System.out :: println);
        //乱序
        Collections.shuffle(integerList1);
        integerList1.stream().forEach(System.out :: println);

    }
    /**
     * 排序3
     */
    @Test
    public void test6() {
        List<String> list1 = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i");
        List<String> list2 = Arrays.asList("d", "c", "b");
        List<String> integerList3 = null;

        //顺序
        Collections.sort(list1);
        list1.stream().forEach(System.out :: println);
        //倒序
        Collections.reverse(list1);
        list1.stream().forEach(System.out :: println);
        //乱序
        Collections.shuffle(list1);
        list1.stream().forEach(System.out :: println);
    }
    /**
     * 排序4
     */
    @Test
    public void test7() {
        List<Date> list1 = Arrays.asList(new Date(1543597200000L), new Date(1543683600000L), new Date(1543770000000L), new Date(1543856400000L), new Date(1543942800000L), new Date(1544029200000L), new Date(1544115600000L), new Date(1544202000000L), new Date(1544288400000L));

        System.out.println("顺序");
        //顺序
        Collections.sort(list1);
        list1.stream().forEach(System.out :: println);
        System.out.println("倒序");
        //倒序
        Collections.reverse(list1);
        list1.stream().forEach(System.out :: println);
        System.out.println("乱序");
        //乱序
        Collections.shuffle(list1);
        list1.stream().forEach(System.out :: println);
    }
    /**
     * 排序5
     */
    @Test
    public void test8() {
        List<Date> list1 = Arrays.asList(new Date(1543597200000L), new Date(1543683600000L), new Date(1543770000000L), new Date(1543856400000L), new Date(1543942800000L), new Date(1544029200000L), new Date(1544115600000L), new Date(1544202000000L), new Date(1544288400000L));

        Map<String,String> stringStringMap=new HashMap<>();
        stringStringMap.put("a","a");
        stringStringMap.put("b","b");
        stringStringMap.put("c","c");
        stringStringMap.put("ab","ab");
        stringStringMap.put("ac","ac");
        stringStringMap.put("ad","ad");

        System.out.println("顺序");
        //顺序
        Collections.sort(list1);
        list1.stream().forEach(System.out :: println);
        System.out.println("倒序");
        //倒序
        Collections.reverse(list1);
        list1.stream().forEach(System.out :: println);
        System.out.println("乱序");
        //乱序
        Collections.shuffle(list1);
        list1.stream().forEach(System.out :: println);
    }

    /**
     * 求两个流的交集，并集
     */
    @Test
    public void test20() {
        List<String> list1 = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i");
        List<String> list2 = Arrays.asList("d", "c", "b");
        List<String> integerList3 = null;


    }

    @Test
    public void test60() {
        System.out.println(LocalDateTime.now().getHour());
    }

    @Test
    public void test61(){
        int canbuy=0;
        Integer count=0;
        if(count.compareTo(0)<1){
            canbuy=1;
        }
        System.out.println(count);
        System.out.println(canbuy);
    }


    @Test
    public void test62(){
        int init=0;
        List<Integer> ids=new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8));
        for (int i = 0; i < ids.size(); i++) {

            System.out.println(i+1+init);
            System.out.println(ids.get(i));
            System.out.println("---");
        }
    }

    /**
     * test63 跨周 年
     *
     * @param
     * @return void
     * @author conceit
     * @date 2022年7月15日 下午3:56
     */
    @Test
    public void test63(){
        LocalDateTime localDateTime=LocalDateTime.of(2022,7,12,31,0,0);
        LocalTime localTimeEnd = LocalTime.MAX;
        LocalTime localTimeStart = LocalTime.MIN;
        LocalDate localDateWeekStart = LocalDate.of(localDateTime.getYear(), localDateTime.getMonthValue(),localDateTime.with(DayOfWeek.MONDAY).getDayOfMonth());
        LocalDate localDateWeekEnd = LocalDate.of(localDateTime.getYear(), localDateTime.getMonthValue(), localDateTime.with(DayOfWeek.SUNDAY).getDayOfMonth());
        LocalDateTime localDateTimeWeekStart=LocalDateTime.of(localDateWeekStart,localTimeStart);
        LocalDateTime localDateTimeWeekEnd =LocalDateTime.of(localDateWeekEnd,localTimeEnd);

        System.out.println(localDateTimeWeekStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        System.out.println(localDateTimeWeekEnd.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }

    @Test
    public void test64(){
        BigDecimal bigDecimal=new BigDecimal("700000");
        //bigDecimal.setScale(2,BigDecimal.ROUND_HALF_UP);
        bigDecimal=bigDecimal.divide(new BigDecimal(60000),2,BigDecimal.ROUND_HALF_UP);
        System.out.println(bigDecimal.toPlainString() + "分钟");
    }
    @Test
    public void test65(){
        List<String> strings=Arrays.asList("11","22","33","44");
        //IndexOutOfBoundsException
        //strings.subList(0,5).stream().forEach(System.out::println);
        strings.stream().limit(5).forEach(System.out::println);
    }


    @Test
    public void test66(){
        List<Integer> int1=Arrays.asList(1,2,3,new Integer(4000000));
        List<Integer> int2=Arrays.asList(1,2,3,4000000);
        List<Integer> int3=Arrays.asList(1,2,3,4,5000000);
        System.out.println(int1.equals(int2));
        System.out.println(int1.equals(int3));
        System.out.println(int2.equals(int3));
    }

    @Test
    public void test67(){
        BigDecimal bigDecimal1=new BigDecimal(-5);
        BigDecimal bigDecimal2=BigDecimal.ZERO;
        System.out.println(BigDecimal.ZERO.compareTo(bigDecimal2)!=1);

        //小于
        System.out.println(bigDecimal1.compareTo(bigDecimal2)!=1);
    }

    @Test
    public void test68(){
        BigDecimal bigDecimal1=new BigDecimal(12);
        BigDecimal bigDecimal2=new BigDecimal(-1);
        BigDecimal bigDecimal3=new BigDecimal(1);
        System.out.println(bigDecimal1.add(bigDecimal2).add(bigDecimal3));
        System.out.println(bigDecimal1.abs());
        System.out.println(bigDecimal2.abs());
    }

    @Test
    public void test69(){
        BigDecimal bigDecimal1=new BigDecimal(-5);
        BigDecimal bigDecimal2=new BigDecimal(3);
        BigDecimal bigDecimal3=new BigDecimal(1);
        System.out.println(bigDecimal1.add(bigDecimal2).add(bigDecimal3));
        System.out.println(bigDecimal1.abs());
        System.out.println(bigDecimal2.abs());
    }

    @Test
    public void test70(){
        BigDecimal bigDecimal1=new BigDecimal(-12);
        BigDecimal bigDecimal2=new BigDecimal(14);
        BigDecimal bigDecimal3=new BigDecimal(1);
        bigDecimal1=bigDecimal1.abs();
        System.out.println(bigDecimal1.subtract(bigDecimal2));
    }

    @Test
    public void test71(){
        BigDecimal bigDecimal1=new BigDecimal(2);
        BigDecimal bigDecimal2=new BigDecimal(14);
        System.out.println(bigDecimal1.subtract(bigDecimal2));

        BigDecimal bigDecimal3=new BigDecimal(12);
        BigDecimal bigDecimal4=new BigDecimal(2);
        System.out.println(bigDecimal3.subtract(bigDecimal4));
    }

    @Test
    public void test72(){
        LocalDate localDate=LocalDate.of(2022,1,1);
        System.out.println(localDate.getYear());
        System.out.println(localDate.getMonth().getValue());
        System.out.println(localDate.getDayOfMonth());
    }

    @Test
    public void test73(){
        String format = DateTimeUtil.format(new Date(), DateTimeUtil.FormatEnum.yyyyMMdd.value);
        //year
        String year=format.substring(0,4);
        //month
        String month=format.substring(4,6);
        //day
        String day=format.substring(6,8);
        System.out.println(format);
        System.out.println(year);
        System.out.println(month);
        System.out.println(day);
    }

    @Test
    public void test74(){

        System.out.println(Boolean.TRUE.hashCode());
        System.out.println(Boolean.FALSE.hashCode());
        System.out.println(true);
        System.out.println(false);
    }

    @Test
    public void test75(){
        System.out.println(buildKey("key","1","2","3"));
    }

    public  String buildKey(String key, String... appends){
        for (String x:appends){
            key=buildKey(key,x);
        }
        return key;
    }
    public  String buildKey(String key, String append){
        if(StrUtil.isNotBlank(key)&&StrUtil.isNotBlank(append)){
            StringBuffer str=new StringBuffer(key);
            str.append(":");
            str.append(append);
            return str.toString();
        }
        else if(StrUtil.isNotBlank(key)){
            return key;
        }
        else if(StrUtil.isNotBlank(append)){
            return append;
        }
        throw new IllegalArgumentException("customKey or append Can't be empty");
    }

    @Test
    public void test76(){

        Deque<Integer> stack=new ArrayDeque();


    }
    @Test
    public void test77(){
        List<Integer>asList=Arrays.asList(1,2,3,4,5,6);
//        System.out.println(asList.size());
//        for (int i = asList.size()-1; i >= 0; i--) {
//            System.out.println("i->"+i);
//            System.out.println(asList.get(i));
//        }
        Collections.reverse(asList);
        asList.stream().forEach(System.out::println);
    }
    @Test
    public void test78(){
        List<Integer>asList=Arrays.asList(1,2,3,4,5,6);
        //Collections.reverse(asList);
        //System.out.println(asList.size());
        //5+0元素=6元素
        //size=6
        //
        for (int i = 0; i < asList.size(); i++) {
//            System.out.println("i->"+i);
//            System.out.println(asList.get(i));
            if(i==asList.size()-1){
                System.out.println(asList.get(i));
            }
        }
        //asList.stream().forEach(System.out::println);
    }


    @Test
    public void test79(){
        LocalDate baseLocalDate=LocalDate.of(2022,1,1);
        WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY,1);
 //       System.out.println(baseLocalDate.get(weekFields.weekOfYear()));
//        LocalDate start=baseLocalDate.plusWeeks(1);
//        LocalDate end=baseLocalDate.plusWeeks(2);
//        System.out.println(start);
//        System.out.println(end);
 //       System.out.println(weekFields.weekOfMonth());
       // System.out.println(ChronoUnit.WEEKS.between(LocalDate.now(),baseLocalDate));
        LocalDate localDate = baseLocalDate.with(weekFields.weekOfYear(),1);
        LocalDate monday=localDate.with(weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
        LocalDate sunday=localDate.with(weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());
        System.out.println(monday);
        System.out.println(sunday);
    }

    @Test
    public void test80(){
        LocalDate one=LocalDate.of(2022,11,1);
        LocalDate two=LocalDate.of(2022,12,1);
        LocalDate there=LocalDate.of(2022,11,1);
        System.out.println(one.isAfter(two));
        System.out.println(one.isBefore(two));
        System.out.println(one.equals(there));
    }

}
